#ifndef __QUATERNION_H__
#define __QUATERNION_H__

#include "BasicType/BasicType_1.h"
#include <assert.h>

namespace GCRE {
	namespace BasicType {
		class Quaternion {
			public:
				Quaternion();
				Quaternion( SFFloat x, SFFloat y, SFFloat z, SFFloat w );
				Quaternion( const Quaternion& q );
				
				SFFloat x() const;
				SFFloat y() const;
				SFFloat z() const;
				SFFloat w() const;
				SFFloat operator[]( SFInt i ) const;
				SFFloat& operator[]( SFInt i );

				void* operator new( size_t size );
				void	operator delete( void *mem );
				void* operator new[]( size_t size );
				void	operator delete[]( void *mem );

				Quaternion& operator=( const Quaternion& q );
				Quaternion operator+( const Quaternion& q ) const;
				Quaternion operator-( const Quaternion& q ) const;
				Quaternion operator*( SFFloat scalar ) const;
				Quaternion operator/( SFFloat scalar ) const;
				Quaternion operator*( const Quaternion& q ) const;
				Quaternion& operator+=( const Quaternion& q );
				Quaternion& operator-=( const Quaternion& q );
				Quaternion& operator*=( const Quaternion& q );
				Quaternion& operator*=( SFFloat scalar );
				Quaternion& operator/=( SFFloat scalar );
				Quaternion operator-() const;
				
				Quaternion Conjugate() const;
				Quaternion Inverse() const;
				Quaternion Log() const;
				Quaternion Exp() const;
				void Set( SFFloat x, SFFloat y, SFFloat z, SFFloat w );
				SFFloat Norm() const;

			protected:

			private:
				union {
					SFFloat data[4];
					__m128 vec;
				};
		};

		inline SFFloat Quaternion::x() const { return data[0]; }
		inline SFFloat Quaternion::y() const { return data[1]; }
		inline SFFloat Quaternion::z() const { return data[2]; }
		inline SFFloat Quaternion::w() const { return data[3]; }
		inline SFFloat Quaternion::operator[]( SFInt i ) const { assert( i >= 0 && i < 4 ); return data[i]; }
		inline SFFloat& Quaternion::operator[]( SFInt i ) { assert( i >= 0 && i < 4 ); return data[i]; }
	}
}

#endif	//	__QUATERNION_H__